package com.uinnova.product.eam.base.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.binary.core.bean.BMProxy;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.base.model.ChangeInfoDto;
import com.uinnova.product.vmdb.comm.model.ci.CcCi;
import com.uinnova.product.vmdb.comm.model.ci.CcCiAttrDef;
import com.uinnova.product.vmdb.comm.model.ci.CcCiClass;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uino.bean.cmdb.base.ESCIClassInfo;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.ESCIRltInfo;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class EamUtil {

	
	/**
	 * 复制对象
	 * 
	 * @param obj
	 *            待复制对象
	 * @param toType
	 *            目标类型
	 * @return
	 */
	public static <T> T copy(Object obj, Class<T> toType) {
		BMProxy<T> proxy = BMProxy.getInstance(toType);
		T t = proxy.newInstance();
		proxy.copyFrom(obj);
		return t;
	}
	
	/**
	 * 复制列表信息 
	 * @param datas
	 * @param toType
	 * @return
	 */
	public static <T> List<T> copy(List<?> datas, Class<T> toType) {
		if (datas == null) {
			return Collections.emptyList();
		}

		List<T> retData = new ArrayList<T>();
		BMProxy<T> proxy = BMProxy.getInstance(toType);
		for (Object obj : datas) {
			T t = proxy.newInstance();
			proxy.copyFrom(obj);
			retData.add(t);
		}
		return retData;
	}

	/**
	 * 复制列表信息
	 * @param datas
	 * @param toType
	 * @return
	 */
	public static <T> List<T> copy(List<?> datas, Class<T> toType, Consumer<T> function) {
		if (datas == null) {
			return Collections.emptyList();
		}

		List<T> retData = new ArrayList<T>();
		BMProxy<T> proxy = BMProxy.getInstance(toType);
		for (Object obj : datas) {
			T t = proxy.newInstance();
			proxy.copyFrom(obj);
			function.accept(t);
			retData.add(t);
		}
		return retData;
	}

	/**
	 * 复制列表信息
	 * @param datas
	 * @param toType
	 * @return
	 */
	public static <E,T> List<T> copy(List<E> datas, Class<T> toType, BiConsumer<? super E, ? super T> action) {
		if (datas == null) {
			return Collections.emptyList();
		}

		List<T> retData = new ArrayList<T>();
		BMProxy<T> proxy = BMProxy.getInstance(toType);
		for (E obj : datas) {
			T t = proxy.newInstance();
			proxy.copyFrom(obj);
			action.accept(obj, t);
			retData.add(t);
		}
		return retData;
	}


	
	/**
	 * 复制分页信息
	 * @param pageData
	 * @param toType
	 * @return
	 */
	public static <T> Page<T> copy(Page<?> pageData, Class<T> toType) {
		if (pageData == null) {
			return null;
		}

		Page<T> ret = new Page<T>();
		List<?> data = pageData.getData();
		
		if(data != null){
			List<T> retData = new ArrayList<T>();
			BMProxy<T> proxy = BMProxy.getInstance(toType);
			for (Object obj : data) {
				T t = proxy.newInstance();
				proxy.copyFrom(obj);
				retData.add(t);
			}
			ret.setData(retData);
		}

		ret.setPageNum(pageData.getPageNum());
		ret.setPageSize(pageData.getPageSize());
		ret.setTotalPages(pageData.getTotalPages());
		ret.setTotalRows(pageData.getTotalRows());
		return ret;
	}


	public static ESCIInfo coverCiInfo(CcCiInfo ci){
		return tranESCIInfo(ci);
	}

	public static List<ESCIInfo> coverCiInfoList(List<CcCiInfo> ciList){
		List<ESCIInfo> list = new ArrayList<>();
		for (CcCiInfo ci : ciList) {
			list.add(coverCiInfo(ci));
		}
		return list;
	}

	public static CcCiInfo coverESCIInfo(ESCIInfo ci, List<CcCiAttrDef> attrDefs, CcCiClass ciClass){
		return tranCcCiInfo(ci, attrDefs, ciClass);
	}

	public static Map<String,String> coverToAttrs(Map<String,Object> attrs){
		Map<String,String> newAttrs = new HashMap<>();
		if(BinaryUtils.isEmpty(attrs)){
			return newAttrs;
		}
		attrs.forEach((k,v) -> {
			if(v != null){
				newAttrs.put(k,String.valueOf(v));
			} else {
				newAttrs.put(k,"");
			}
		});
		return newAttrs;
	}

	public static CcCiInfo coverESCIInfoOptimize(ESCIInfo ci, List<CcCiAttrDef> attrDefs, ESCIClassInfo ciClass){
		ciClass.setCcAttrDefs(new ArrayList<>());
		return tranCcCiInfo(ci, attrDefs, ciClass);
	}


/*	public static Map<String,Object> coverToAttrsObj(Map<String,String> attrs){
		Map<String,Object> newAttrs = new HashMap<>();
		if(BinaryUtils.isEmpty(attrs)){
			return newAttrs;
		}
		attrs.forEach((k,v) -> {
			if(v != null){
				newAttrs.put(k,v);
			}else {
				newAttrs.put(k,"");
			}
		});
		return newAttrs;
	}*/


	/**
	 * ES CI对象-ESCIInfo转化成CcCiInfo
	 * @param esCI
	 * @param ciClass
	 *  是否包含分类信息
	 * @return
	 */
	/*public static CcCiInfo tranCcCiInfo(ESCIInfo esCI, ESCIClassInfo ciClass) {
		if (esCI == null) { return null; }
		String jsonStr = JSON.toJSONString(esCI, SerializerFeature.WriteMapNullValue).replaceAll("null", "''");
		JSONObject json = JSON.parseObject(jsonStr);
		CcCiInfo ciInfo = JSON.toJavaObject(json, CcCiInfo.class);
		CcCi ci = JSON.toJavaObject(json, CcCi.class);
		// CcCiInfo添加版本标识
		Long version = esCI.getVersion() == null ? 0 : esCI.getVersion();
		ci.setCiVersion(String.valueOf(version));
		ciInfo.setCi(ci);
		if (!BinaryUtils.isEmpty(ciClass)) {
			ciInfo.setCiClass(ciClass);
			ciInfo.setAttrDefs(ciClass.getCcAttrDefs());
		}
		return ciInfo;
	}*/

	public static CcCiInfo tranCcCiInfo(ESCIInfo esCI, List<CcCiAttrDef> attrDefs, CcCiClass ciClass) {
		if (esCI == null) { return null; }
		String jsonStr = JSON.toJSONString(esCI, SerializerFeature.WriteMapNullValue).replaceAll("null", "''");
		JSONObject json = JSON.parseObject(jsonStr);
		CcCiInfo ciInfo = JSON.toJavaObject(json, CcCiInfo.class);
		CcCi ci = JSON.toJavaObject(json, CcCi.class);
		// CcCiInfo添加版本标识
		Long version = esCI.getVersion() == null ? 0 : esCI.getVersion();
		ci.setCiVersion(String.valueOf(version));
		ciInfo.setCi(ci);
		if (!BinaryUtils.isEmpty(ciClass)) {
			ciInfo.setCiClass(ciClass);
		}
		if(!BinaryUtils.isEmpty(attrDefs)){
			ciInfo.setAttrDefs(attrDefs);
		}
		return ciInfo;
	}

	/**
	 * ES CI对象-CcCiInfo转化成ESCIInfo
	 *
	 * @param ciInfo
	 * 该CI所属分类的全部属性
	 * @return
	 */
	public static ESCIInfo tranESCIInfo(CcCiInfo ciInfo) {
		String jsonStr = JSON.toJSONString(ciInfo.getCi());
		JSONObject json = JSON.parseObject(jsonStr);
		ESCIInfo esCI = JSON.toJavaObject(json, ESCIInfo.class);
		String ciVersion = ciInfo.getCi().getCiVersion();
		if (BinaryUtils.isEmpty(ciVersion) || ciVersion.equals("0")) {
			ciVersion = "1";
		}
		esCI.setVersion(Long.parseLong(ciVersion));
		if (!BinaryUtils.isEmpty(ciInfo.getAttrs())) {
			String ms = JSON.toJSONString(ciInfo.getAttrs());
			esCI.setAttrs(JSON.parseObject(ms));
		}
		return esCI.ciAttrformat();
	}

	/*public static void tranESCIInfo(ESCIInfo esCI) {
		String ciVersion = esCI.getCiVersion();
		if (BinaryUtils.isEmpty(ciVersion) || ciVersion.equals("0")) {
			ciVersion = "1";
		}
		esCI.setVersion(Long.parseLong(ciVersion));
	}*/
	/*public static ESCIClassInfo tranESCIClassInfo(CcCiClassInfo clsInfo) {
		String jsonStr = JSON.toJSONString(clsInfo.getCiClass());
		JSONObject json = JSON.parseObject(jsonStr);
		ESCIClassInfo esCI = JSON.toJavaObject(json, ESCIClassInfo.class);
		if (clsInfo.getAttrDefs() != null) {
			esCI.setCcAttrDefs(clsInfo.getAttrDefs());
		}
		return esCI;
	}*/

	public List<CcCiInfo> transEsInfoList(List<ESCIInfo> esInfos) {
		List<CcCiInfo> ciInfos = new ArrayList<>();
		if (BinaryUtils.isEmpty(esInfos)) { return ciInfos; }
		for (ESCIInfo esciInfo : esInfos) {
			String jsonStr = JSON.toJSONString(esciInfo, SerializerFeature.WriteMapNullValue).replaceAll("null", "''");
			JSONObject json = JSON.parseObject(jsonStr);
			CcCiInfo ciInfo = JSON.toJavaObject(json, CcCiInfo.class);
			CcCi ci = JSON.toJavaObject(json, CcCi.class);
			Long version = esciInfo.getVersion() == null ? 1 : esciInfo.getVersion();
			ci.setCiVersion(String.valueOf(version));
			ciInfo.setCi(ci);
			ciInfos.add(ciInfo);
		}
		return ciInfos;
	}

	/**
	 *  根据标识转换视图dirType字段
	 */
	public static Integer transDirType(Integer type) {
		switch (type) {
			case 1:
				// 其他业务架构
				return 1;
			case 10:
				// 流程建模
				return null;
			case 3:
				// 应用架构
				return 11;
			case 100:
				// 组件建模
				return null;
			case 4:
				// 数据架构
				return 101;
			case 5:
				// 技术架构
				return 111;
			default: {
				return null;
			}
		}
	}

	/**
	 *  关系数据添加私有库设计库版本属性
	 * @param esciRltInfo
	 * @param localVersion
	 * @param publishVersion
	 * @return
	 */
	public static ESCIRltInfo setVersionAttrs (ESCIRltInfo esciRltInfo, Long localVersion, Long publishVersion) {
		esciRltInfo.setLocalVersion(localVersion);
		esciRltInfo.setPublicVersion(publishVersion);
		return esciRltInfo;
	}

	/**
	 * 去除字符串中特殊字符
	 */
	public static String replaceSpecialStr(String str){
		String regEx="[\\s~·`!！@#￥$%^…&*()\\-—_=+【\\[\\]】｛{}｝、\\\\；;：:‘'“”\"，,《/？?]";
		Pattern pattern= Pattern.compile(regEx);
		Matcher matcher = pattern.matcher(str);
		return matcher.replaceAll("");
	}

	public static <T> ChangeInfoDto<T> compareLists(List<T> list1, List<T> list2) {
		ChangeInfoDto<T> changes = new ChangeInfoDto();
		List<T> added = new ArrayList<>();
		List<T> removed = new ArrayList<>();

		for (T item : list1) {
			if (!list2.contains(item)) {
				removed.add(item);
			}
		}

		for (T item : list2) {
			if (!list1.contains(item)) {
				added.add(item);
			}
		}

		changes.setAdd(added);
		changes.setDelete(removed);
		return changes;
	}
	
}
